<template>
<div class="mind">
    <div class="left">
        <div class="left-content">
            <div class="tip">您的需求？</div>
            <el-input
                v-model="state.text"
                :autosize="{ minRows: 4, maxRows: 8 }"
                type="textarea"
                :disabled="state.loading"
                placeholder="请输入您想要生成内容的简单描述、AI将为您输出一份完整的markdown内容及其思维导图!"
            />
            <div class="button">
                <a-button
                    type="primary"
                    @click="chatmind"
                    :loading="state.loading"
                >
                    智能生成生成思维导图
                </a-button>
            </div>
            <div class="tip">
                <h4>内容需求</h4>
                <el-button link @click="onUseDemo">试试示例</el-button>
            </div>
            <el-input
                v-model="state.markdown"
                :autosize="{ minRows: 10, maxRows: 16 }"
                type="textarea"
                placeholder="请输入markdown的内容"
            />
        </div>
        <div class="bottom">
            <span>每次使用消耗基础积分： 1</span>
            <el-button-group>
                <el-button type="info" @click="exportHTML">导出HTML</el-button>
                <el-button type="primary" @click="exportPNG">导出PNG</el-button>
                <el-button type="warning" @click="exportSVG">导出SVG</el-button>
            </el-button-group>
        </div>
    </div>
    <div class="content">
        <div class="header">
            <h2>思维导图</h2>
        </div>
        <div class="mind-box" ref="mindBox">
            <svg ref="svgRef" />
        </div>
    </div>
</div>
</template>

<script setup lang="ts">
import {reactive, onMounted, onUpdated, ref, watch, inject} from 'vue'
import { Transformer } from 'markmap-lib'
import { Markmap } from 'markmap-view'
import html2canvas from 'html2canvas';
import { mind } from '/@/api/frontend/chat/tool'
import {useUserInfo} from "/@/stores/userInfo"
import { message } from "ant-design-vue"


const userInfo = useUserInfo()

const state: {
    loading: boolean
    login_show: boolean,
    text: string
    markdown: string
    demoData: string
} = reactive({
    loading: false,
    login_show: inject('login_show', ref(false)),
    text: '',
    markdown: '',
    demoData: `
# 会议流程

## 开场白
- 欢迎词
- 自我介绍

## 议程安排
- 介绍会议议程
- 确认议程是否被所有人接受

## 上一次会议的总结
- 回顾上次会议的议题及结果
- 确认上次会议的行动项是否已经完成

## 主题讨论
- 提出本次会议的主题
- 介绍主题相关背景信息
- 提出问题并进行讨论
- 形成共识或决策

## 行动项
- 确定行动项及责任人
- 确定完成时间和目标

## 公告和其他事项
- 公告即将到来的活动或项目
- 公告公司的其他事项

## 结束语
- 感谢所有人的参与
- 总结会议内容
- 确认下一次会议的时间和议题
`,
})

// 生成思维导图
const transformer = new Transformer();
const mm = ref()
const svgRef = ref()
const mindBox = ref()

const initValue = ref(`
# 在线AI助手
## 基础功能
- 支持AI聊天
- 支持GPT4
- 支持DLLAE2
- 支持Midjourney
- 更多功能等你探索......

## 更多内容
-  在上面输入您想要生成的内容
- 点击生成即可
`);
const update = () =>{
    const { root } = transformer.transform(state.markdown);
    mm.value.setData(root);
    mm.value.fit();
}

watch(()=>state.markdown,(n)=>{
    // 监听输入变化更新思维导图
    update()
})
onMounted(()=>{
    // 初始化markmap思维导图
    mm.value = Markmap.create(svgRef.value);
    state.markdown = initValue.value
    // 更新思维导图渲染
    update();
})
const onUseDemo = () => {
    state.markdown = state.demoData
}

const chatmind = async () => {
    // 判断是否登录
    if (!userInfo.isLogin()) {
        state.login_show = !state.login_show
        return false
    }

    // 判断消息是否为空
    if (!state.text) {
        message.warning('请输入您想要生成内容的简单描述')
        return
    }


    const response = await mind({
        text: state.text
    })
    const content_type = response.headers.get('content-type');
    if (content_type?.indexOf('application/json') === 0) {
        const result = await response.json();
        // 提示
        if (result.code == 1) {
            message.success(result.msg)
        } else {
            message.error(result.msg)
        }
        return
    }
    // 消息动作
    state.markdown = ''
    state.loading = true
    // 开始循环消息
    const reader = response.body!.getReader();
    const decoder = new TextDecoder();

    let partialLine = '';
    while (true) {
        const { done, value } = await reader.read();
        if (done) {
            state.loading = false
            break;
        }

        const decodedText = decoder.decode(value, { stream: true });
        const chunk = partialLine + decodedText;
        const newLines = chunk.split(/\r?\n/);
        partialLine = newLines.pop() ?? "";

        for (const line of newLines) {
            if (line.length === 0) continue
            if (line.startsWith(":")) continue
            if (line === "data: [DONE]" || line.indexOf('data: [DONE]') === 0) {
                state.loading = false
                return
            }

            // try {
            //     const result = JSON.parse(line.substring(6))
            //     if (result) {
            //         state.markdown = state.markdown + result.content
            //     }
            // } catch (error) {
            //     return
            // }

            try {
                const trimmedLine = line.trim(); // 去除行首尾的空格
                if (trimmedLine.startsWith('data:')) {
                    const jsonData = trimmedLine.slice(5); // 去除 "data:" 前缀
                    const json = JSON.parse(jsonData);
                    if (json.choices) {
                        for (const choice of json.choices) {
                            const content = choice.delta?.content;
                            if (content) {
                                state.markdown = state.markdown + content
                            }
                        }
                    }
                }
            } catch (error) {
                console.error(error);
            }

        }
    }
}

const exportHTML = () => {
    exportSVG()
}

const exportPNG = () => {
    html2canvas(mindBox.value).then(canvas => {
        const img = canvas.toDataURL('image/png')
        const a = document.createElement('a')
        a.href = img
        a.download = 'mind.png'
        a.click()
    })
}

const exportSVG = () => {
    const svgData = new XMLSerializer().serializeToString(svgRef.value)
    const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.download = 'mind.svg'
    a.href = url
    a.click()
    URL.revokeObjectURL(url)
}
</script>

<style scoped lang="scss">
html {
    .mind {
        .left {
            background-color: var(--bg-color);
        }
    }
}
.mind {
    display: flex;
    height: 100vh;
    background-color: var(--bg-color);
    .left {
        display: flex;
        flex-direction: column;
        width: 320px;
        height: 100%;
        border-right: 2px solid #e7ecf6;
        background-color: #e7ecf6;
        .left-content {
            flex: 1;
            padding: 16px;
            .tip {
                display: flex;
                justify-content: space-between;
                align-items: center;
                color: #606266;
                margin-bottom: 8px;
                h4 {
                    font-weight: bold;
                    color: #303133;
                }
            }
            .button {
                margin: 16px 0;
                .ant-btn {
                    width: 100%;
                }
            }
        }
        .bottom {
            display: flex;
            flex-direction: column;
            align-items: center;
            height: 100px;
            padding: 16px;
            border-top: 2px solid #e7ecf6;
            span {
                color: #606266;
                margin-bottom: 8px;
            }
        }
    }
    .content {
        display: flex;
        flex-direction: column;
        flex: 1;
        height: 100%;
        padding: 16px;
        .header {
            padding: 4px 0 20px 0;
            h2 {
                font-size: 24px;
                font-weight: bold;
            }
        }
        .mind-box {
            flex: 1;
            border: 2px solid #e5e7eb;
            border-radius: 4px;
            height: 100%;
            svg {
                width: 100%;
                height: 100%;
            }
        }
    }
}
@media screen and (max-width: 768px) {
    .mind {
        flex-direction: column;
        .left {
            display: none;
        }
        .content {

        }
    }
}
</style>
